06 内核初始化
初始化进程管理
set_task_stack_end_magic(&init_task)
系统创建的第一个进程,0 号进程。
初始化系统调用
trap_init() 设置中断门(Interrupt Gate),用于处理各种中断。
初始化内存管理
sched_init() 初始化调度模块
vfs_caches_init() 初始化基于内存的文件系统 rootfs
了兼容各种各样的文件系统,需要将文件的相关数据结构和操作抽象出来,形成一个抽象层对上提供统一的接口,叫做 VFS(Virtual File System)虚拟文件系统。
初始化 1 号进程
rest_init 用 kernel_thread(kernel_init, NULL, CLONE_FS) 创建第二个进程,即 1 号进程。1 号进程将运行一个用户进程。
访问关键资源的代码放在 Ring0,称为内核态(Kernel Mode);普通的程序代码放在 Ring3,称为用户态(User Mode)。
处于用户态的代码无法执行更高权限的指令,可通过系统调用访问资源。
当一个用户态的程序运行到一半,要访问一个核心资源(访问网卡发一个网络包),需要暂停当前的运行,调用系统调用,接下来就轮到内核中的代码运行。内核将该包在网卡上排队,轮到时发送。发送完系统调用结束,返回用户态,暂停 运行的程序继续运行。
用户态 -> 系统调用 -> 保存寄存器 -> 内核态执行系统调用 -> 恢复寄存器 -> 返回用户态 -> 继续运行
从内核态到用户态
在在内核态执行 kernel_thread 函数启动 1 号进程,运行 run_init_process 函数调用 do_execve,指令指针寄存器指向用户态函数栈的栈顶,下一条指令就从用户态开始运行。
ramdisk
ramdisk 是基于内存的文件系统,运行 ramdisk 上的 /init,完成后就在用户态了。/init 先根据存储系统的类型加载驱动,之后就可以设置真正的根文件系统,并启动文件系统上的 init。接下做各种系统的初始化,启动系统的服务、控制台,用户才可以登录。
创建 2 号进程
再次使用 kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES) 函数创建第三个进程,即 2 号进程,函数 kthreadd 负责所有内核态的线程的调度和管理,是内核态所有线程运行的祖先。